package com.leoman.category.service.impl;

import com.leoman.category.dao.CategoryDao;
import com.leoman.category.entity.Category;
import com.leoman.category.service.CategoryService;
import com.leoman.common.service.impl.GenericManagerImpl;
import com.leoman.entity.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by 蔡琦 on 2016/6/21 0021.
 *
 */
@Service
public class CategoryServiceImpl extends GenericManagerImpl<Category, CategoryDao> implements CategoryService {

    @Autowired
    private CategoryDao categoryDao;

    /*@Override
    public List<Category> findByType(Integer type) {
        return categoryDao.findType(type);
    }*/

    @Override
    public List<Category> findType(Integer type) {
        return categoryDao.findType(type);
    }

    @Override
    public List<Category> iFindList() {
        return categoryDao.iFindList();
    }

    @Override
    public Page<Category> page(final Integer type, Integer pageNum, Integer pageSize) {
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, Sort.Direction.ASC, "showTurn");

        Page<Category> page = categoryDao.findAll(new Specification<Category>() {
            @Override
            public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();

                if (type != null) {
                    Predicate pre = cb.equal(root.get("type").as(Integer.class), type);
                    predicateList.add(pre);
                } else {
                    Predicate pre = cb.ge(root.get("type").as(Integer.class), Constant.CATEGORY_TYPE_004);
                    predicateList.add(pre);

                    Predicate pre2 = cb.le(root.get("type").as(Integer.class), Constant.CATEGORY_TYPE_006);
                    predicateList.add(pre2);

                }

                Predicate pre3 = cb.equal(root.get("status").as(Integer.class), 0);
                predicateList.add(pre3);
//                Subquery<Category> subquery = query.subquery(Category.class);
//                Predicate pre = subquery.in(1,2,3);
//                predicateList.add(pre);

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }


                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, pageRequest);

        return page;
    }

    @Override
    public Page<Category> findPage(final Integer type, final Integer status, Integer pageNum, Integer pageSize) {
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id");

        Page<Category> page = categoryDao.findAll(new Specification<Category>() {
            @Override
            public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();

                if (type != null) {
                    Predicate pre = cb.equal(root.get("type").as(Integer.class), type);
                    predicateList.add(pre);
                }

                if (status != null) {
                    Predicate pre = cb.equal(root.get("status").as(Integer.class), status);
                    predicateList.add(pre);
                }

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, pageRequest);

        return page;
    }

    @Override
    @Transactional
    public void saveEdit(HttpServletRequest request, String name, Long categoryId, Integer type, @RequestParam(value = "imageFile", required = false) MultipartFile file) {

        //String msg = request.getParameter("name");
        //String name = new String(msg.getBytes("ISO-8859-1"), "UTF-8");

    }

    @Override
    @Transactional
    public Integer changeShowTurn(Long categoryId, Integer turn) {
        Category baseCategory = categoryDao.findOne(categoryId);
        Category sourceCategory = categoryDao.getByShowTurn(turn == 0 ? baseCategory.getShowTurn() - 1 : baseCategory.getShowTurn() + 1);
        Integer showTurn;

        if (null == sourceCategory) {
            if (turn == 0) {
                // 已经是第一条了，无法上移
                return -1;
            } else {
                // 已经是最后一条了，无法下移
                return -2;
            }
        } else {
            showTurn = sourceCategory.getShowTurn();
            sourceCategory.setShowTurn(baseCategory.getShowTurn());
            categoryDao.save(sourceCategory);

            baseCategory.setShowTurn(showTurn);
            categoryDao.save(baseCategory);

            return 1;
        }
    }

    @Override
    public Category getShowTurn(Integer turn) {
        List<Category> list = categoryDao.findListByShowTurn();

        if (null != list && list.size() > 0) {
            if (turn == 0) {
                return list.get(0);
            } else {
                return list.get(list.size() - 1);
            }
        }

        return null;
    }

    @Override
    public void updateShowTurn(Integer turn) {

        List<Category> categoryList = categoryDao.changeShowTurnByTurn(turn);
        for (Category category : categoryList) {
            category.setShowTurn(category.getShowTurn() - 1);
            categoryDao.save(category);
        }

    }

    @Override
    public Category findOneById(Long categoryId) {
        return categoryDao.findOne(categoryId);
    }
}
